﻿//******************************************************************************************************
//  NotificationDispatcher.cs - Gbtc
//
//  Copyright © 2013, Grid Protection Alliance.  All Rights Reserved.
//
//  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
//  the NOTICE file distributed with this work for additional information regarding copyright ownership.
//  The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
//  not use this file except in compliance with the License. You may obtain a copy of the License at:
//
//      http://www.opensource.org/licenses/eclipse-1.0.php
//
//  Unless agreed to in writing, the subject software distributed under the License is distributed on an
//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
//  License for the specific language governing permissions and limitations.
//
//  Code Modification History:
//  ----------------------------------------------------------------------------------------------------
//  04/19/2013 - Stephen C. Wills
//       Generated original version of source code.
//
//******************************************************************************************************

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace SIEGate.Core.Notifications
{
    public enum BroadcastNotification
    {
        Start,
        Restart,
        Shutdown,
        Pause,
        ConfigChange
    }

   
    public class BroadcastNotificationArgs : EventArgs
    {
        public readonly BroadcastNotification Message;
        private object[] arguments;

        public BroadcastNotificationArgs(BroadcastNotification message, params object[] arguments)
        {
            this.Message = message;
            this.arguments = arguments;
        }

        public IReadOnlyCollection<object> Arguments
        {
            get
            {
                return new ReadOnlyCollection<object>(arguments);
            }
        }
    }

    public class TargetedNotififcationArgs : EventArgs
    {
        public readonly string Message;
        private object[] arguments;

        public TargetedNotififcationArgs(string message, params object[] arguments)
        {
            this.Message = message;
            this.arguments = arguments;
        }
         public IReadOnlyCollection<object> Arguments
        {
            get
            {
                return new ReadOnlyCollection<object>(arguments);
            }
        }
    }

    public class NotificationDispatcher
    {
        #region [ Members ]

        // Delegates
        public delegate object RoutedSignalHandler(object sender, object[] args);

        // Events

        public event EventHandler<BroadcastNotificationArgs> Broadcasts;

        // Fields
        private IDictionary<uint,NotificationReceiver> m_routeTargets;

        #endregion

        #region [ Constructors ]

        public NotificationDispatcher()
        {
            m_routeTargets = new Dictionary<uint, NotificationReceiver>();
        }

        #endregion

        #region [ Methods ]

        public void SendBroadcast(BroadcastNotification message, params object[] args)
        {
            if (Broadcasts != null)
            {
                // todo perhaps we need a way to deal exceptions (e.g. returning them)
                Broadcasts(this, new BroadcastNotificationArgs(message, args));
            }
        }

        public void SendSignal(uint receiverID, string message, params object[] args)
        {
            m_routeTargets[receiverID].MessageReceived(new TargetedNotififcationArgs(message, args));
        }

        public INotificationReceiver GetReceiver(IConfigInfo target)
        {
            NotificationReceiver res = new NotificationReceiver(this, target.ID);
            if (target is INotificationTarget)
            {
                m_routeTargets[target.ID] = res;
            }
            return res;
        }
        #endregion

    }
}
